package com.yyj.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import com.yyj.pojo.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

/**
 * 公众平台通用接口工具类
 * 
 * @author zhongwen ho
 */
public class WeixinUtil {

	private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);

	/**
	 * 发起https请求并获取结果
	 * 
	 * @param requestUrl
	 *            请求地址
	 * @param requestMethod
	 *            请求方式（GET、POST）
	 * @param outputStr
	 *            提交的数据
	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
	 */
	public static JSONObject httpRequest(String requestUrl,
			String requestMethod, String outputStr) {
		JSONObject jsonObject = null;
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
			TrustManager[] tm = { new MyX509TrustManager() };
			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
			sslContext.init(null, tm, new java.security.SecureRandom());
			// 从上述SSLContext对象中得到SSLSocketFactory对象
			SSLSocketFactory ssf = sslContext.getSocketFactory();

			URL url = new URL(requestUrl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url
					.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);

			if ("GET".equalsIgnoreCase(requestMethod))
				httpUrlConn.connect();

			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}

			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(
					inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(
					inputStreamReader);

			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}
			bufferedReader.close();
			inputStreamReader.close();
			// 释放资源
			inputStream.close();
			inputStream = null;
			httpUrlConn.disconnect();
			jsonObject = JSONObject.parseObject(buffer.toString());
		} catch (ConnectException ce) {
			log.error("Weixin server connection timed out.");
		} catch (Exception e) {
			log.error("https request error:{" + e + "}");
		}
		return jsonObject;
	}

	// 获取access_token的接口地址（GET） 限200（次/天）
	public final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

	/**
	 * 获取access_token
	 * 
	 * @param appid
	 *            凭证
	 * @param appsecret
	 *            密钥
	 * @return
	 */
	public static AccessToken getAccessToken(String appid, String appsecret) {
		AccessToken accessToken = null;

		String requestUrl = access_token_url.replace("APPID", appid).replace(
				"APPSECRET", appsecret);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			try {
				accessToken = new AccessToken();
				accessToken.setToken(jsonObject.getString("access_token"));
				accessToken.setExpiresIn(jsonObject.getInteger("expires_in"));
			} catch (JSONException e) {
				accessToken = null;
				// 获取token失败
				log.info("获取token失败 errcode:{"
						+ jsonObject.getInteger("errcode") + "} errmsg:{"
						+ jsonObject.getString("errmsg") + "}");
			}
		}
		return accessToken;
	}

	// 获取jsapi_ticket的接口地址（GET） 限200（次/天）
	public final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";

	/**
	 * 获取jsapi_ticket
	 * 
	 * @param accessToken
	 * 
	 * @return
	 */
	public static JsapiTicket getJsapiTicket(String accessToken) {
		JsapiTicket jsapiTicket = null;

		String requestUrl = jsapi_ticket_url.replace("ACCESS_TOKEN",
				accessToken);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			try {
				jsapiTicket = new JsapiTicket();
				jsapiTicket.setTicket(jsonObject.getString("ticket"));
				jsapiTicket.setExpiresIn(jsonObject.getInteger("expires_in"));
			} catch (JSONException e) {
				accessToken = null;
				// 获取token失败
				log.info("获取JsapiTicket失败 errcode:{"
						+ jsonObject.getInteger("errcode") + "} errmsg:{"
						+ jsonObject.getString("errmsg") + "}");
			}
		}
		return jsapiTicket;
	}

	// 菜单创建（POST） 限100（次/天）
	public static String menu_create_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";

	/**
	 * 创建菜单
	 * 
	 * @param menu
	 *            菜单实例
	 * @param accessToken
	 *            有效的access_token
	 * @return 0表示成功，其他值表示失败
	 */
	public static int createMenu(Menu menu, String accessToken) {
		int result = 0;

		// 拼装创建菜单的url
		String url = menu_create_url.replace("ACCESS_TOKEN", accessToken);
		// 将菜单对象转换成json字符串
		String jsonMenu = JSONObject.toJSONString(menu);
		// 调用接口创建菜单
		JSONObject jsonObject = httpRequest(url, "POST", jsonMenu);

		if (null != jsonObject) {
			if (0 != jsonObject.getInteger("errcode")) {
				result = jsonObject.getInteger("errcode");
				log.error("创建菜单失败 errcode:{" + jsonObject.getInteger("errcode")
						+ "} errmsg:{" + jsonObject.getString("errmsg") + "}");
			}
		}

		return result;
	}

	private static String code_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

	/**
	 * 获取网页授权凭证
	 * 
	 * @param appId
	 *            公众账号的唯一标识
	 * @param appString
	 *            公众账号的密钥
	 * @param code
	 * @return WeixinOauth2Token
	 */
	public static WeixinOauth2Token getOauth2AccessToken(String appId,
                                                         String appSecret, String code) {

		WeixinOauth2Token wat = null;

		String requestUrl = code_url.replace("APPID", appId)
				.replace("SECRET", appSecret).replace("CODE", code);
		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
		log.info(JSON.toJSONString(jsonObject));
		if (null != jsonObject) {
			try {
				wat = new WeixinOauth2Token();
				wat.setAccessToken(jsonObject.getString("access_token"));
				wat.setExpiresIn(jsonObject.getIntValue("expires_in"));
				wat.setRefreshToken(jsonObject.getString("refresh_token"));
				wat.setOpenId(jsonObject.getString("openid"));
				wat.setScope(jsonObject.getString("scope"));
			} catch (Exception e) {
				wat = null;
				int errorCode = jsonObject.getInteger("errcode");
				String errorMsg = jsonObject.getString("errmsg");

				log.error("获取网页授权凭证失败  errcode:{" + errorCode + "}  errmsg:{"
						+ errorMsg + "}");
				log.error(e.getMessage(), e);
			}
		}
		return wat;
	}

	private static String refresh_token_url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN";

	/**
	 * 刷新网页授权凭证
	 * 
	 * @param appId
	 *            公众账号的唯一标识
	 * @param refreshToken
	 * @return WeixinOauth2Token
	 */
	public static WeixinOauth2Token refreshOauth2AccessToken(String appId,
			String refreshToken) {
		WeixinOauth2Token wat = new WeixinOauth2Token();

		String requestUrl = refresh_token_url.replace("APPID", appId).replace(
				"REFRESH_TOKEN", refreshToken);
		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
		if (null != jsonObject) {
			try {
				wat.setAccessToken(jsonObject.getString("access_token"));
				wat.setExpiresIn(jsonObject.getInteger("expires_in"));
				wat.setRefreshToken(jsonObject.getString("refresh_token"));
				wat.setOpenId(jsonObject.getString("openid"));
				wat.setScope(jsonObject.getString("scope"));
			} catch (Exception e) {
				wat = null;
				int errorCode = jsonObject.getInteger("errcode");
				String errorMsg = jsonObject.getString("errmsg");

				log.error("刷新网页授权凭证失败  errcode:{" + errorCode + "}  errmsg:{"
						+ errorMsg + "}");

				log.error(e.getMessage(), e);
			}
		}
		return wat;
	}

	private static String user_info_url = "https://api.weixin.qq.com/sns/userinfo?openid=OPENID&access_token=ACCESS_TOKEN";

	/**
	 * 通过网页授权凭证获取用户信息
	 * 
	 * @param appId
	 *            公众账号的唯一标识
	 * @param refreshToken
	 * @return WeixinOauth2Token
	 */
	public static SNSUserInfo getSnsUserInfo(String openId, String accessToken) {
		SNSUserInfo snsUserInfo = null;

		String requestUrl = user_info_url.replace("OPNEID", openId).replace(
				"ACCESS_TOKEN", accessToken);

		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
		if (null != jsonObject) {
			try {
				snsUserInfo = new SNSUserInfo();
				snsUserInfo.setOpenId(jsonObject.getString("openid"));
				snsUserInfo.setNickName(jsonObject.getString("nickname"));
				snsUserInfo.setSex(jsonObject.getInteger("sex"));
				snsUserInfo.setProvice(jsonObject.getString("province"));
				snsUserInfo.setCountry(jsonObject.getString("country"));
				snsUserInfo.setCity(jsonObject.getString("city"));
				snsUserInfo.setHeadImageUrl(jsonObject.getString("headimgurl"));
			} catch (Exception e) {
				snsUserInfo = null;
				int errorCode = jsonObject.getInteger("errcode");
				String errorMsg = jsonObject.getString("errmsg");

				log.error("通过网页授权凭证获取用户信息  errcode:{" + errorCode
						+ "}  errmsg:{" + errorMsg + "}");

				log.error(e.getMessage(), e);
			}
		}
		return snsUserInfo;
	}

	private static String customer_url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";

	/**
	 * 发送客服消息
	 * 
	 * @param accessToken
	 *            接口访问凭证
	 * @param jsonMsg
	 *            格式的客服消息（包括touser.msgtype 和消息内容）
	 * @return
	 */
	public static boolean sendCustomMessage(String accessToken, String jsonMsg){
		log.info("消息内容为：" + jsonMsg);
		boolean result = false;
		// 拼接请求地址
		String requestUrl = customer_url.replace("ACCESS_TOKEN", accessToken);
		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "POST",
				jsonMsg);
		if (null != jsonObject) {
			Integer errorCode = jsonObject.getInteger("errcode");
			String errorMsg = jsonObject.getString("errmsg");
			if (0 == errorCode) {
				result = true;
				log.info("客服发送消息成功--->errorCode:" + errorCode + ",errorMsg:"
						+ errorMsg);
			} else {
				log.error("客服发送消息失败--->errorCode:" + errorCode + ",errorMsg:"
						+ errorMsg);
			}
		}
		return result;
	}

	// 获取二维码ticket
	private static String qr_code_ticket_url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=ACCESS_TOKEN";

	/**
	 * 创建二维码
	 * 
	 * @param accessToken
	 *            接口访问凭证
	 * @param expireSeconds
	 *            有效时间
	 * @param sceneId
	 *            场景ID
	 * @param actionType
	 *            1:临时；2：永久；3：永久字符串类型
	 * @return
	 */
	public static WeiXinQRCode createQRCode(String accessToken, String sceneInfo) {

		WeiXinQRCode weiXinQRCode = new WeiXinQRCode();
		String requestUrl = qr_code_ticket_url.replace("ACCESS_TOKEN",
				accessToken);

		// 需要提交的参数
		String jsonMsg = "{\"action_name\":\"QR_LIMIT_STR_SCENE\",\"action_info\":{\"scene\":{\"scene_str\":\"SCENE_STR\"}}}";

		// action_name为 QR_LIMIT_STR_SCENE时报错，该方法等微信方面修改回复
		/*
		 * String actionName = null; if (actionType == 1) actionName =
		 * "QR_SCENE"; else if (actionType == 2) actionName = "QR_LIMIT_SCENE";
		 * else if (actionType == 3) actionName = "QR_LIMIT_STR_SCENE";
		 */
		jsonMsg = jsonMsg.replace("SCENE_STR", sceneInfo);

		// 创建带参数的二维码 String.format(jsonMsg, expireSeconds)
		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "POST",jsonMsg);
		if (null != jsonObject) {
			try {
				weiXinQRCode.setExpireSeconds(jsonObject
						.getIntValue("expire_seconds"));
				weiXinQRCode.setTicket(jsonObject.getString("ticket"));

				log.info("获取创建二维码 ticket成功；ticket:" + weiXinQRCode.getTicket());
			} catch (Exception e) {
				log.error(e.getMessage(), e);
			}
		}
		return weiXinQRCode;
	}

	// 换取二维码URL
	private static String qr_code_url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET";

	

	// 获取在线客户信息URL
	private static String custom_onlina_info_url = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist?access_token=ACCESS_TOKEN";

	/**
	 * 获取在线客服信息
	 * 
	 * @param accessToken
	 * @return
	 */
	public static List<CustomOnlineInfo> getCustomOnlineInfos(String accessToken) {

		List<CustomOnlineInfo> cois = new ArrayList<CustomOnlineInfo>();

		String requestUrl = custom_onlina_info_url.replace("ACCESS_TOKEN",
				accessToken);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			try {
				JSONArray jsonArray = jsonObject.getJSONArray("kf_online_list");
				for (Iterator<Object> iterator = jsonArray.iterator(); iterator
						.hasNext();) {
					CustomOnlineInfo co = (CustomOnlineInfo) jsonArray.get(0);
					cois.add(co);
				}
			} catch (JSONException e) {
				accessToken = null;
				// 获取token失败
				log.info("获取JsapiTicket失败 errcode:{"
						+ jsonObject.getInteger("errcode") + "} errmsg:{"
						+ jsonObject.getString("errmsg") + "}");
			}
		}
		return cois;
	}

	// 获取客户会话状态信息URL
	private static String customer_talking_info_url = "https://api.weixin.qq.com/customservice/kfsession/getsession?access_token=ACCESS_TOKEN&openid=OPENID";

	/**
	 * 获取客户会话信息
	 * 
	 * @param accessToken
	 * @return
	 */
	public static CustomerTalking getCustomerTalkingInfos(String accessToken, String openId) {
		CustomerTalking ct = null;
		
		String requestUrl = customer_talking_info_url.replace("ACCESS_TOKEN",
				accessToken).replace("OPENID", openId);
		JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			try {
				Integer errCode = jsonObject.getInteger("errcode");
				if(errCode == 0){
					ct = new CustomerTalking();
					ct.setKf_account(jsonObject.getString("kf_account"));
					ct.setErrCode(errCode);
					ct.setErrmsg(jsonObject.getString("errmsg"));
					ct.setCreatetime(jsonObject.getString("createtime"));
				}
			} catch (JSONException e) {
				accessToken = null;
				// 获取token失败
				log.info("获取JsapiTicket失败 errcode:{"
						+ jsonObject.getInteger("errcode") + "} errmsg:{"
						+ jsonObject.getString("errmsg") + "}");
			}
		}
		return ct;
	}

	/**
	 * URL编码（UTF8）
	 * 
	 * @param source
	 * @return
	 */
	public static String urlEncodeUTF8(String source) {
		String result = null;
		try {
			result = URLEncoder.encode(source, "utf-8");
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return result;
	}

	private static String mp_code_url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";

	/**
	 * 小程序通过code授权获取openId
	 *
	 * @param appId
	 * @param appSecret
	 * @param code
	 * @return WeixinOauth2Token
	 */
	public static MpAuthInfo getMpAuthInfo(String appId, String appSecret , String code) {
		MpAuthInfo mpAuthInfo = null;

		String requestUrl = mp_code_url.replace("APPID", appId).replace(
				"SECRET", appSecret).replace(
				"JSCODE", code);

		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
		log.info("getMpAuthInfo:{}" , jsonObject.toJSONString());
		if (null != jsonObject) {
			try {
				if(!jsonObject.containsKey("errcode")){
					mpAuthInfo = new MpAuthInfo();
					mpAuthInfo.setOpenId(jsonObject.getString("openid"));
					mpAuthInfo.setSessionKey(jsonObject.getString("session_key"));
				}else{
					Integer errCode = jsonObject.getInteger("errcode");
					String errorMsg = jsonObject.getString("errmsg");
					log.error("小程序通过code授权获取openId  errcode:{" + errCode
							+ "}  errmsg:{" + errorMsg + "}");
				}
			} catch (Exception e) {
				mpAuthInfo = null;
				int errorCode = jsonObject.getInteger("errcode");
				String errorMsg = jsonObject.getString("errmsg");

				log.error("小程序通过code授权获取openId  errcode:{" + errorCode
						+ "}  errmsg:{" + errorMsg + "}");

				log.error(e.getMessage(), e);
			}
		}
		return mpAuthInfo;
	}

	private static String send_template_msg = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=ACCESS_TOKEN";

	/**
	 *
	 * @param accessToken
	 * @param jsonMsg
	 * @return
	 */
	public static JSONObject sendTemplateMsg(String accessToken, JSONObject jsonMsg) {

		String requestUrl = send_template_msg.replace("ACCESS_TOKEN" , accessToken);
		JSONObject jsonObject = WeixinUtil.httpRequest(requestUrl, "POST",jsonMsg.toJSONString());
		if (null != jsonObject) {
			try {
				Integer errCode = jsonObject.getInteger("errcode");
				if(errCode == 0){
					log.info("发送模板消息成功>>>>touser:[{}]" , jsonMsg.getString("touser"));
				}else{
					log.info("发送模板消息失败 errcode:{"
							+ jsonObject.getInteger("errcode") + "} errmsg:{"
							+ jsonObject.getString("errmsg") + "}");
				}
			} catch (Exception e) {
				log.info("发送模板消息失败 errcode:{"
						+ jsonObject.getInteger("errcode") + "} errmsg:{"
						+ jsonObject.getString("errmsg") + "}");
			}
		}
		return null;
	}



}
